package com.xs;

import lombok.Data;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @program: paxos-java-demo
 * @description 提议者
 * @author: wzx
 * @create: 2021-07-08 17:34
 **/

@Data
public class Proposer {
    private String name; //提案者名称

    public Proposer(String name) {
        this.name = name;
    }

    public static List<Proposal> proposals = new CopyOnWriteArrayList<>();

    /**
     * 提案者选定一个提案向一半以上的Acceptor发送请求
     *
     * @param proposal
     * @param acceptors
     */
    public void vote(Proposal proposal, Collection<Acceptor> acceptors) {
        int quorum = Math.floorDiv(acceptors.size(), 2) + 1; //一半以上的Acceptor
        int count = 0;
        while (true) {
            Utils.printInfo(name+",提案", "发起", proposal.getNo()+"");
            //已经同意的提案

            for (Acceptor acceptor : acceptors) {
                //分别向每个人发起
                Promise promise = acceptor.onPrepare(proposal);
                if (promise != null && promise.isAck()) {
                    //决议通过
                    proposals.add(promise.getProposal());
                }
            }
            //决议数小于一半人
            if (proposals.size() < quorum) {
                Utils.printInfo("PROPOSER[" + proposal + "]", "VOTE", "NOT PREPARED");
                proposal = Proposal.nextProposal(proposal.getNo(), proposals); //换一个提案继续提交
                continue;
            }

            int acceptCount = 0; //
            for (Acceptor acceptor:acceptors){
                if(acceptor.onAccept(proposal))
                    acceptCount++;
            }

            //如果接受人数<投票者人数
            if(acceptCount<quorum)
            {
                Utils.printInfo("PROPOSER[" + proposal + "]", "VOTE", "NOT ACCEPTED");
                proposal = Proposal.nextProposal(proposal.getNo(), proposals); //换下一个提案
                continue;
            }
            Utils.printInfo("PROPOSER[" + proposal + "]", "选举", "**********************成功********************");
        }

    }
}
